package cn.example.vip.mall.util;

import com.alibaba.fastjson.JSON;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

public class JwtToken {
	
	public static final	String DEFAULT_SECRET = "srpingcloudalibaba";
	
	public static String createToken(Map<String, Object> dataMap){
		return createToken(dataMap, DEFAULT_SECRET);
	}
	
	/**
	 * 创建 Token 令牌
	 * @param dataMap
	 * @param secret
	 * @return
	 */
	public static String createToken(Map<String,Object> dataMap, String secret){
		// 确认秘钥(是否为空，是则为默认秘钥)
		if(secret==null){
			secret = DEFAULT_SECRET;
		}
		// 确认签名算法
		Algorithm algorithm = Algorithm.HMAC256(secret);	// 加密数据
		/*
		 * JWT令牌数据
		 * iss:jwt签发者
		 * sub:主题
		 * aud:接收jwt的一方
		 * exp:jwt过期时间
		 * nbf:定义在什么时间之前，该jwt都是不可用的
		 * iat:jwt的签发时间
		 * jti:jwt的唯一身份标识，主要用来作为一次性 token ，从而回避重放攻击
		 * */
		// Jwt令牌创建
		return JWT.create()
			.withClaim("body", dataMap)	// 封装自定义载荷
			.withIssuer("test")	//签发者
			.withSubject("JWT令牌")	// 主题
			.withAudience("member")	// 接收方
			.withExpiresAt(new Date(System.currentTimeMillis() + 3600000))	// 过期时间 3600s
			.withNotBefore(new Date(System.currentTimeMillis() + 1000))	// 多久后才能使用 1s
			.withIssuedAt(new Date())		// 签发时间
			.withJWTId(UUID.randomUUID().toString().replace("-",""))		// 唯一身份id
			.sign(algorithm);	// 加密算法
	}
	
	/**
	 * 默认秘钥的令牌解析
	 * @param token
	 * @return
	 */
	public static Map<String, Object> parseToken(String token){
		return parseToken(token, DEFAULT_SECRET);
	}
	
	/**
	 * 令牌解析
	 * @param token
	 * @param secret
	 * @return
	 */
	public static Map<String, Object> parseToken(String token, String secret){
		// 确认秘钥
		if(secret==null){
			secret = DEFAULT_SECRET;
		}
		// 确认签名算法
		Algorithm algorithm = Algorithm.HMAC256(secret);
		// 创建令牌校验对象
		JWTVerifier verifier = JWT.require(algorithm).build();
		// 校验解析
		DecodedJWT jwt = verifier.verify(token);
		return jwt.getClaim("body").as(Map.class);
	}
	
	/**
	 * 令牌创建于解析测试！！！
	 * @param args
	 * @throws InterruptedException
	 */
	public static void main_test(String[] args) throws InterruptedException {
		// 创建令牌
		Map<String, Object> dataMap = new HashMap<>();
		dataMap.put("name", "test");
		dataMap.put("address", "chongqing");
		
		// 创建令牌
		String token = JwtToken.createToken(dataMap, DEFAULT_SECRET);
		System.out.println(token);
		
		// 等待生效并校验令牌
		TimeUnit.SECONDS.sleep(2);
		Map<String, Object> result = parseToken(token, DEFAULT_SECRET);
		System.out.println(JSON.toJSONString(result));
	}
	
}
